package socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {
    private ServerSocket serverSocket;
    private ExecutorService threadPool;
    private List<PrintWriter> allOut; // 存储所有客户端的输出流

    public Server() {
        try {
            System.out.println("正在启动服务端...");
            serverSocket = new ServerSocket(8088);
            threadPool = Executors.newFixedThreadPool(30);
            allOut = new ArrayList<>(); // 初始化集合
            System.out.println("服务端启动完毕...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        try {
            while (true) {
                System.out.println("等待客户端链接...");
                Socket socket = serverSocket.accept();
                System.out.println("一个客户端链接了!");
                // 启动一个线程来处理该客户端的交互
                ClientHandler handler = new ClientHandler(socket);
                threadPool.execute( handler);
//                Thread t = new Thread(handler);
//                t.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Server server = new Server();
        server.start();
    }

    /**
     * 广播消息给所有客户端
     */
    private synchronized void broadcast(String message) {
        // 将消息发送给所有客户端
        for (PrintWriter out : allOut) {
            out.println(message);
        }
    }

    /**
     * 该线程的任务是负责与指定的客户端进行交流
     */
    private class ClientHandler implements Runnable {
        private Socket socket;
        private String host; // 客户端地址信息

        public ClientHandler(Socket socket) {
            this.socket = socket;
            // 获取客户端的地址信息
            host = socket.getInetAddress().getHostAddress();
        }

        public void run() {
            PrintWriter pw = null;
            try {
                // 获取输出流，用于给客户端发送消息
                OutputStream out = socket.getOutputStream();
                pw = new PrintWriter(out, true);

                // 将该客户端的输出流存入共享集合
                synchronized (Server.this) {
                    allOut.add(pw);
                }

                // 广播欢迎信息
                broadcast(host + "加入了聊天室!");

                // 获取输入流，读取客户端发送的消息
                InputStream in = socket.getInputStream();
                Scanner scanner = new Scanner(in, StandardCharsets.UTF_8);

                String message;
                while (scanner.hasNextLine()) {
                    message = scanner.nextLine();
                    // 广播给所有客户端
                    broadcast(host + "说: " + message);
                }
            } catch (IOException e) {
                // 异常通常是客户端断开连接导致的
            } finally {
                // 处理客户端断开连接的操作
                if (pw != null) {
                    synchronized (Server.this) {
                        allOut.remove(pw);
                    }
                }
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                broadcast(host + "离开了聊天室!");
            }
        }
    }
}